use std::any::{Any, TypeId};

/// 反射( Reflect)机制一般是指程序自我访问 、检测和修改其自身状态或行为的能力 。 Rust
/// 标准库提供了 std::any::Any 来支持运行时反射。
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_any() {
        start();
    }
}

fn start() {
    let arr = ["sb", "zz", "fw", "ff"];
    print(&arr);
    let arr = vec!["sb", "zz", "fw", "ff"];
    print(&arr);

    let v1 = 0xc0ffee_u32;
    let v2 = E::He;
    let v3 = S { x: 1, y: 2, z: 3 };
    let v4 = "rust";
    let mut a: &dyn Any;

    // 从代码中看得出来 ， TypeId 是一个结构体，其字段t存储了一串数字 ，
    // 这就是全局唯一类型标识符， 实际上是 u64类型。 代表唯一标识符的这串数字，在不同的编译环境中，
    // 产生的结果是不同的。所以在实际开发中，最好不要将 TypeId 暴露到外部接口中被当作依赖。
    a = &v1;
    assert!(a.is::<u32>());
    println!("{:?}", TypeId::of::<u32>());

    a = &v2;
    assert!(a.is::<E>());
    println!("{:?}", TypeId::of::<E>());

    a = &v3;
    assert!(a.is::<S>());
    println!("{:?}", TypeId::of::<S>());

    a = &v4;
    assert!(a.is::<&str>());
    println!("{:?}", TypeId::of::<&str>());

    // 转换到具体类型
    // Any 也提供了 downcast_ref和 downcast_mut 两个成对的泛型方法，
    // 用于将泛型 T 向下 转换为具体的类型，返回值分别为 Option<&T>和 Option<&mut T>类型。
    // 其中 downcast_ref 将类型 T 转换为 不可变引用，而 downcast_mut 将类型 T 转换为可变引用 。
    // 代码展示了downcast_ref的用法

    fn print_any(v: &dyn Any) {
        if v.is::<&str>() {
            println!("{:?}", v.downcast_ref::<&str>());
        }
        // 也可以
        if let Some(v) = v.downcast_ref::<&str>() {
            println!("str = [{}]", v);
        } else if let Some(v) = v.downcast_ref::<i32>() {
            println!("i32 = [{}]", v);
        } else if let Some(v) = v.downcast_ref::<u32>() {
            println!("u32 = [{}]", v);
        } else if let Some(v) = v.downcast_ref::<E>() {
            println!("E = [{:?}]", v);
        } else if let Some(v) = v.downcast_ref::<S>() {
            println!("S = [{:?}]", v);
        }
    }

    print_any(&0xc0ffee_u32);
    print_any(&E::He);
    print_any(&"rust");
    print_any(&S { x: 0, y: 0, z: 0 });

    // 也可以使用box Any
    fn print_box_any(v: Box<dyn Any>) {
        if v.is::<&str>() {
            println!("{:?}", v.downcast_ref::<&str>());
        }
        // 也可以
        if let Some(v) = v.downcast_ref::<&str>() {
            println!("str = [{}]", v);
        } else if let Some(v) = v.downcast_ref::<i32>() {
            println!("i32 = [{}]", v);
        } else if let Some(v) = v.downcast_ref::<u32>() {
            println!("u32 = [{}]", v);
        } else if let Some(v) = v.downcast_ref::<E>() {
            println!("E = [{:?}]", v);
        } else if let Some(v) = v.downcast_ref::<S>() {
            println!("S = [{:?}]", v);
        }
    }

    print_box_any(Box::new(0xc0ffee_u32));
    print_box_any(Box::new(E::He));
    print_box_any(Box::new("rust"));
    print_box_any(Box::new(S { x: 0, y: 0, z: 0 }));

    // 非静态生命周期类型没有实现 Any
    let a = 42;
    let v = UnStatic { x: &a };
    let mut any: &dyn Any;
    // any = &v; `a` does not live long enough  编译错误

    // 使用静态生命周期类型的值创建 UnStatic实例
    static STATUS: UnStatic = UnStatic { x: &32 };
    any = &STATUS;
    assert!(any.is::<UnStatic>());

    // ANSWER，其生命周期是静态的，其引用 &ANSWER也是静态的。所以在函数中，
    // 使用&ANSWER创建的 Unstatic实例 v的生 命周期也是静态的
    let v = UnStatic { x: &ANSWER };
    any = &STATUS;
    assert!(any.is::<UnStatic>());
}

static ANSWER: i32 = 42;

fn print(arr: &[&str]) {
    for i in arr {
        println!("杨林是 {}", i);
    }
}

#[derive(Debug)]
enum E {
    H,
    He,
    Li,
}

#[derive(Debug)]
struct S {
    x: i32,
    y: u8,
    z: u16,
}

#[derive(Debug)]
struct UnStatic<'a> {
    x: &'a i32,
}
